#include <algorithm>
#include <cstdlib>  // Header file needed to use srand and rand
#include <iostream>
#include <unordered_set>
#include <fstream>
#include <stack>

#include"pulse_optical.h"
#include"graph.h"
#include"dijkstra.h"
#include "pulse_optical.cc"
#include"dijkstra.cc"

int main(){
    Graph test(9);

    std::ifstream Nodes("Nodes.txt", std::ios::in);
    if(!Nodes.is_open()){
		std::cout<<"Open file Nodes failed"<<std::endl;
		return 0;
	}else{
		std::cout<<"Open file Nodes successed"<<std::endl;
	}

    int node_id = 0;
    int type = 0;
    
    while(Nodes>>node_id){
        Nodes>>type;
        test.addNodes(node_id, type);
    }
    Nodes.close();


    std::ifstream Links("Links.txt", std::ios::in);
     if(!Links.is_open()){
		std::cout<<"Open file Links failed"<<std::endl;
		return 0;
	}else{
		std::cout<<"Open file Links successed"<<std::endl;
	}

    int link_id =1;
    int source_id;
    int ter_id;
    double cost;
    double delay;
    int type_units;
    std::vector<int> v1 = {1, 2};
    std::vector<int> v2 = {2, 3};
    std::vector<int> v3 = {2};
    while(Links>>source_id){
        Links>>ter_id>>cost>>delay>>type_units;
        switch (type_units)
        {
        case 0:
            test.addLinks(link_id, source_id, ter_id, cost, delay, Omega);
            link_id++;
            test.addLinks(link_id, ter_id, source_id, cost, delay, Omega);
            link_id++;
            break;
        case 1:
            test.addLinks(link_id, source_id, ter_id, cost, delay, v1);
            link_id++;
            test.addLinks(link_id, ter_id, source_id, cost, delay, v1);
            link_id++;
            break;
        case 2:
            test.addLinks(link_id, source_id, ter_id, cost, delay, v2);
            link_id++;
            test.addLinks(link_id, ter_id, source_id, cost, delay, v2);
            link_id++;
            break;
        case 3:
            test.addLinks(link_id, source_id, ter_id, cost, delay, v3);
            link_id++;
            test.addLinks(link_id, ter_id, source_id, cost, delay, v3);
            link_id++;
            break;
        default:
            break;
        }       
    }
    Links.close();

    test.makeGraph0();
    std::stack<Flow> flows_Dijfailed;

    std::ifstream Flows("Flows.txt", std::ios::in);
    if(!Flows.is_open()){
		std::cout<<"Open file Flows failed"<<std::endl;
		return 0;
	}else{
		std::cout<<"Open file Flows successed"<<std::endl;
	}

    int flow_id = 1;
    int from;
    int to;
    while(Flows>>from){
        Flows>>to;
        Flow test_flow(flow_id, from, to);
        dijkstra dij;
        dij.SetupTopology(&test);
        std::cout<<"dijkstra\n";
        Path result = dij.FindPath(test_flow);
        std::cout<<"dijkstra OK\n";
        if(result.cost>8){
            flows_Dijfailed.push(test_flow);
        }else{
        result.Print();
        }

        flow_id++;
    }
    Flows.close();

    test.makeGraph2();
    Pulse_optical pulse_1;
    pulse_1.SetupTopology(&test);
    std::stack<Flow> flows_Pulfailed;
    while(!flows_Dijfailed.empty()){
        Flow test_flow = flows_Dijfailed.top();
        flows_Dijfailed.pop();
        std::cout << "FindPath\n";
        Path result = pulse_1.FindPath(test_flow);
        std::cout << "FindPath OK\n";
        if(result.delay>50){
            flows_Pulfailed.push(test_flow);
        }else{
             result.Print();
        }
       
    }
   
    test.makeGraph1();
    Pulse_optical pulse_2;
    pulse_2.SetupTopology(&test);
    while(!flows_Pulfailed.empty()){
        Flow test_flow = flows_Pulfailed.top();
        flows_Pulfailed.pop();
        std::cout << "FindPath\n";
        Path result = pulse_2.FindPath(test_flow);
        std::cout << "FindPath OK\n";
        result.Print();
    }
    
    
    return 0;
}